package cn.monkey.family.server.domain.uc.user;

import cn.monkey.family.data.Result;
import cn.monkey.family.data.Results;
import cn.monkey.family.data.context.RequestContext;
import cn.monkey.family.data.crud.AbstractEntityCrudService;
import cn.monkey.family.data.uc.user.*;
import cn.monkey.family.data.uc.user.role.UserRoleBindRequest;
import cn.monkey.family.data.uc.user.role.UserRoleMapper;
import cn.monkey.family.data.uc.user.role.UserRoleVo;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.Optional;

@Service
public class UserService extends AbstractEntityCrudService<UserQueryRequest, User, UserDto, UserVo, UserMapper, UserRepository>
        implements IUserService {

    protected final UserRoleMapper userRoleMapper;

    protected final UserRoleBindEventListener userRoleBindEventListener;

    public UserService(UserRepository repository,
                       UserMapper mapper,
                       UserRoleMapper userRoleMapper,
                       UserRoleBindEventListener userRoleBindEventListener) {
        super(repository, mapper);
        this.userRoleMapper = userRoleMapper;
        this.userRoleBindEventListener = userRoleBindEventListener;
    }

    @Override
    public Result<UserRoleVo> readUserRole(RequestContext context, String id) {
        return this.repository.findById(id)
                .map(this.userRoleMapper::toVo)
                .map(Results::ok)
                .orElse(Results.fail("USER_NOT_EXISTS"));
    }

    @Override
    public Result<UserRoleVo> bindUserRole(RequestContext requestContext,
                                           String uid,
                                           UserRoleBindRequest userRoleBindRequest) {
        Optional<User> userOptional = this.repository.findById(uid);
        return userOptional.map(user -> this.userRoleBindEventListener.onUserRoleBind(requestContext, user, userRoleBindRequest))
                .orElse(Results.fail("USER_NOT_EXISTS"));
    }

    @Override
    public Result<Page<UserRoleVo>> readUserRole(RequestContext requestContext, UserQueryRequest request, Pageable pageable) {
        Page<User> userPage = this.repository.findPageByQueryRequest(request, pageable);
        if (userPage.isEmpty()) {
            return Results.ok(Page.empty(pageable));
        }
        List<UserRoleVo> userRoleVos = this.userRoleMapper.toVos(userPage.getContent());
        return Results.ok(new PageImpl<>(userRoleVos, pageable, userPage.getTotalElements()));
    }
}
